// ProjectName: go-learn-demo
// PackageName: redisybxb
// Description:
// Author: hy.bai
// Date: 2025-08-25 星期一 10:45

package redisybxb

import (
	"fmt"
	"log/slog"
)

// Hash类型的数据：Hash(哈希)是⼀种数据类型，它类似于⼀个键值对的集合(集合的元素是一个键值对)

func RedisHSet() {
	var client, ctx, err = InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// name-hk是hash类型的数据的key，username是字段名, hy.bai是字段值
	intCmd := client.HSet(*ctx, "name-hk", "username", "hy.bai", "password", "ybxb8615") // *指针类型的变量：获取指针指向的值
	slog.Info(fmt.Sprintf("status: %d", intCmd.Val()))
}

func RedisHGet() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 根据key和field字段，查询field字段的值
	stringCmd := client.HGet(*ctx, "name-hk", "username")
	fmt.Println(stringCmd.Val())
}

func RedisHGetAll() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 据key查询Map映射中的所有字段和值
	mapCmd := client.HGetAll(*ctx, "name-hk")
	valMap := mapCmd.Val() // 返回值类型是：map[string]string
	for key, val := range valMap {
		fmt.Println(key, ":", val)
	}
}

func RedisHIncrBy() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 累加count字段的值,⼀次性累加2， name-hk为hash类型的key
	// 注意:如果count属性不存在，则会新增
	intCmd := client.HIncrBy(*ctx, "name-hk", "count", 1)
	slog.Info(fmt.Sprintf("结果: %d", intCmd.Val()))
}

// 根据key返回所有field字段名，结果是⼀个string数组
func RedisHKeys() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 返回所有field字段名
	ssCmd := client.HKeys(*ctx, "name-hk")
	vals := ssCmd.Val()
	for _, val := range vals {
		fmt.Println(val)
	}
}

// 根据key返回所有field字段名，结果是⼀个string数组
func RedisHLen() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 返回field字段的个数
	intCmd := client.HLen(*ctx, "name-hk")
	fmt.Println(intCmd.Val())
}

// 根据key和多个字段名，批量查询多个hash字段值
func RedisHMGet() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 根据key和多个字段名，批量查询多个hash字段值
	propCmd := client.HMGet(*ctx, "name-hk", "username", "password", "count")
	vals := propCmd.Val()
	for ind := range vals {
		fmt.Println(vals[ind])
	}
}

func RedisHSetNX() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 添加字段，如果字段已经存在，则不添加,返回false，如果字段不存在，则会添加，返回true
	boolCmd := client.HSetNX(*ctx, "name-hk", "id", "1000")
	fmt.Println(boolCmd.Val())
}

func RedisHExists() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 检测指定的hash类型数据中，是否存在指定的字段。存在返回true,不存在返回false
	boolCmd := client.HExists(*ctx, "name-hk", "username")
	fmt.Println(boolCmd.Val())
}

// 删除一个或多个字段
func RedisHDel() {
	client, ctx, err := InitClient()
	if err != nil {
		slog.Error(fmt.Sprintf("Redis Init Error: %s", err.Error()))
	}
	// 检测指定的hash类型数据中，是否存在指定的字段。存在返回true,不存在返回false
	boolCmd := client.HDel(*ctx, "name-hk", "count", "password")
	fmt.Println(boolCmd.Val())
	// 查询指定key的所有字段和字段值。
	RedisHGetAll()
}

// 当前go文件的调用入口
func TestHash() {
	// RedisHDel()
	RedisHGetAll()
}
